
#include "Base.h"
#include "Entities/BaseEntity.h"

#include "Transform3DComponent.h"
#include "Entities/Component.h"
#include "Entities/ComponentMessageEnum.h"
#include "../ComponentTypeEnum.h"
#include "../Events/BaseEntityEvents.h"

#include <Memory/DebugNew.h>

namespace CasaEngine
{

Transform3DComponent::Transform3DComponent(BaseEntity* pEntity_) :
	TransformComponent(pEntity_, TRANSFORM_3D),
		m_pParentTransform(NULL)
{
	m_LocalScale.Set(1.0f, 1.0f, 1.0f);

	registerEventFunc(this, &Transform3DComponent::OnParentChange);
}

Transform3DComponent::~Transform3DComponent()
{

}

void Transform3DComponent::Initialize()
{

}

//all entities must implement an update function
void  Transform3DComponent::Update(const GameTime& /*gameTime_*/)
{

}


void Transform3DComponent::SetLocalMatrix(Matrix4 val) 
{ 
	m_LocalMatrix = val;
	m_LocalMatrixChanged = true;
}

void Transform3DComponent::SetWorldMatrix(Matrix4 val) 
{ 
	m_WorldMatrix = val;
}


Vector3F Transform3DComponent::GetLocalPosition() const 
{ 
	return m_LocalPosition; 
}

void Transform3DComponent::SetLocalPosition(Vector3F val) 
{ 
	m_LocalPosition = val;
	m_LocalMatrixChanged = true;
}

float Transform3DComponent::GetLocalRotation() const 
{ 
	return m_LocalRotation; 
}
void Transform3DComponent::SetLocalRotation(float val) 
{ 
	m_LocalRotation = val;
	m_LocalMatrixChanged = true;
}

Vector3F Transform3DComponent::GetLocalScale() const 
{ 
	return m_LocalScale; 
}

void Transform3DComponent::SetLocalScale(Vector3F val) 
{ 
	m_LocalScale = val;
	m_LocalMatrixChanged = true;
}

/**
 * 
 */
Vector3F Transform3DComponent::GetPosition() const 
{ 
	return m_pParentTransform == NULL ? m_LocalPosition : m_LocalPosition + m_pParentTransform->GetPosition();
}

/**
 * 
 */
float Transform3DComponent::GetRotation() const 
{ 
	return m_pParentTransform == NULL ? m_LocalRotation : m_LocalRotation + m_pParentTransform->GetRotation(); 
}

/**
 * 
 */
Vector3F Transform3DComponent::GetScale() const 
{ 
	return m_pParentTransform == NULL ? m_LocalScale : m_LocalScale + m_pParentTransform->GetScale(); 
}


/*
 *	
 */
void Transform3DComponent::OnParentChange(const EntityParentChangeEvent* /*pEvent_*/)
{
	BaseEntity* pParent = GetEntity()->GetParent();

	if (pParent != NULL)
	{
		m_pParentTransform = pParent->GetComponentMgr()->GetComponent<Transform3DComponent>();
	}
	else
	{
		m_pParentTransform = NULL;
	}

	UpdateWorldMatrix();
}

/*
 *	
 */
void Transform3DComponent::UpdateLocalMatrix()
{
	if (m_LocalMatrixChanged == true)
	{
		m_LocalMatrixChanged = false;

		Matrix4 matS, matRot;
		matS.CreateScale(m_LocalScale.x, m_LocalScale.y, 1.0f);
		matRot.CreateRotationZ(m_LocalRotation);

		m_LocalMatrix = matS * matRot;
		m_LocalMatrix.SetTranslation(m_LocalPosition.x, m_LocalPosition.y, 0.0f);
	}
}

/*
 *	
 */
void Transform3DComponent::UpdateWorldMatrix()
{
	UpdateLocalMatrix();

	if (m_pParentTransform != NULL)
	{
		m_WorldMatrix = m_LocalMatrix * m_pParentTransform->GetWorldMatrix();
	}
	else
	{
		m_WorldMatrix = m_LocalMatrix;
	}
}

/**
 *
 */
void Transform3DComponent::Write(std::ostream& /*os*/) const
{

}

/**
 * 
 */
void Transform3DComponent::Read (std::ifstream& /*is*/)
{

}



} // namespace CasaEngine
